package com.runvp.common.pay.alipay;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.runvp.common.config.AlipayConfig;
import com.runvp.common.util.OrderNoUtils;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;

@Slf4j
public class AlipayClient {
//    /**
//     * 信用服务ID
//     */
//    public String SERVICE_ID = "2021041800000000000083681100";
//    //商户PID
//    public String PAYEE_USER_ID = "2088631147159119";
//    public String ALIPAY_NETWORK = "https://openapi.alipay.com/gateway.do";
//    public String APP_ID = "2021002122629875";
//    public String APP_PRIVATE_KEY = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQChVAIMkheei6D1ZO9vk0cCUHEaIwQ/jchkYcOB7d07HpkKs5BIxbOjDocEbugf3Yw0FzoYB73u0KcuIm9dh/hMnJeWzNtGyc70OjXWO42NNDvH9wMls15FGVGykSHPhnQkuPTXhWhw6P3EdZkMMXU7ZD+9z7VZqU2hQS9ajBUFqtyfJRkEbHPZ8ET7iW9i8ywEAM7UUg21BxQ952/1Ai4IRsYFtXRwZvyTG+RyeeqjMSEcgpOB4Mcq2Yew/lR/Gs5y8Ccc0ZNjrhyu3jCMalkpyYraygIGyzYm5BSGXweVTBU4sBla59+ZS39NpOxQIu+13qY4Cbhoz7S+ElO8nfjFAgMBAAECggEBAICeMjgFbRE4rq2VuBKTL2SX72PwEN3+Uoo9Kxp2Ig+VGFxgxiJOhCX2Wgxdw3BMOA/7iJRJ79Hqxa5RQ8oksf+aRHy0fAlWsUki83MF7Zdq0lJdC0ROWVTrl6eub288+XGhh4of0SFbj53GR6th7t3X0b2pUCLYiIyMJI2i6sulo13dICE1OnzpAvsgu92OwMbStae1gHQ07BdIG5OF+sE8y66SWVpGghygs91kha8QHorVr6NZlrIUVLLp6xLiVh3e+lqYUYWFF7NK1cvnbSro/w37K8xMzmosumTYHsb/JcTwzdLKHOJadckrtAXKQMIIqtzJgl1wEUfMI/cIrO0CgYEA5bh/Pudu3828kpOemU7XcEisdbOpxzCuxFaUIUJdhzVPcNaoj86R1m0c+pO/9XXkLiuZsyYf1WCBS2sB1GMgk6N1dyIPhw7rKdfZIu6SEDHQ/lA/Zj8NVWfL7I6f2CDSMJuG6TdX3Jm7G2evUb4O4yUxK7R/jGnp68Nx4+ulzSsCgYEAs8iYmn13lIl1SeB5SGUbEftUrdH9A3UV8gQk3Bj+UDFjioityrwQ2pS7nWu9hjZmbw7u8xlpauQTyzasCLsrOdMawHlFx1Xj7ANLgRtQKJ6mbTzWW48FU1Q2pMXZ/PV/glZFPA6IoSzZd6F+oqIKN7+7Qb1gvC1LelxGI1Zbuc8CgYEAqcZP7Hp4e9j+W8nTtfQJzsc3BgoRGNCG6T4fXfFBVDL3EirjCt0c9T9Q4nQds1g8mk7I2hj7/+PByq47/O6B3fs5TiGTHjrNW/BVXra4plVa4wkFwhgpT4xVru+9fKrNDPV0oJmxSq0nFlrrvFrdf8w16doNRgXkxsR8QHkg4V8CgYEAm5+2yXR2QLPEPZD8K3ipuCURJe2x0H5X4slHhuZzrcMy4UZy+h1VkYBR73DF/Bm3Dcele/WxVP/dSnkm7d/nCQT+EUJo7qYgx7oKb9XOy3qZodGZ1GO3PmyVaIiDq/5uw8od4GDMUIhcLrwyvGD760oitENUK1AiF+csJ4anm+0CgYAfsZrF+cxJG/a7NrInjCH3MoswagibhH9wGHI7Jnh82qncT7ag9EK/sNyY4FhfpDumnmeeXwqLLZPe3Q5RnYfvBpgOttnUExnKlfFCL6SbxbzdaE39CECbyoDdRQ5RNuhQRIUwH+VXi9/fykHiidbMrkUyduuLEmT/JB8jpkWjUA==";
//    public String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmNCWx9eR79VsfwYTcu6LxAa/1OiMzul5f17tonWvn0LDKXEybq+AFdaf4tS76jca3AkYrzCxgbLZFhUl+s+KuBTWCfUoWPxU3/0wH2+YWdS/M+ySZgCuMwHeNjiWl76TrMbQ24COXqM7t5zjCkOP7LA9CXGM91Yob50VLBfOzUYQHWr6zAtBvV5Iw2C9QJbsDe5f9CCumNI7irFQFjP4cHuS0WunyQRxDES1gPLpAlMoOtJ/bvmheN8RWpgHjWF6laXiUdE6ZmitMniaBl+xL8L/GO3qx6qTpCGtUnCM6TarPrPstp+I2CCmtHFq5T5eYInzVJ5AvJckPS0RsNE/QIDAQAB";
//    //    public static String NOTIFY_URL = "https://rents.runvp.com/apppay/alipay/notify";
//    public String NOTIFY_URL = "https://rents.runvp.com/app/alipay/notify";
    public static String CHARSET = "UTF-8";
    public static String SIGN_TYPE = "RSA2";

   public static DefaultAlipayClient alipayClient;

    /**
     * 初始化客户端
     */
    static {
        alipayClient = new DefaultAlipayClient(AlipayConfig.getAlipayNetwork(), AlipayConfig.getAppId(), AlipayConfig.getAppPrivateKey(), "json", CHARSET, AlipayConfig.getAlipayPublicKey(), "RSA2");
    }
    /**
     * 冻结金额
     *
     * @throws AlipayApiException
     */
    public String fundAuthOrderAppFreeze(String outOrderNo, BigDecimal depositAmount, String fundAmount) {
        try {
            String outRequestNo = OrderNoUtils.getOrderNo();
            log.info("outOrderNo: " + outOrderNo);
            log.info("outRequestNo: " + outRequestNo);
            AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest();
            AlipayFundAuthOrderAppFreezeModel model = new AlipayFundAuthOrderAppFreezeModel();
            model.setOrderTitle("支付宝预授权");
            model.setOutOrderNo(outOrderNo); //替换为实际订单号
            model.setOutRequestNo(outRequestNo); //替换为实际请求单号，保证每次请求都是唯一的
            model.setPayeeUserId(AlipayConfig.getPayeeUserId()); //payee_user_id,Payee_logon_id不能同时为空
            model.setProductCode("PRE_AUTH_ONLINE"); //PRE_AUTH_ONLINE为固定值，不要替换
            model.setAmount(fundAmount);
            //需要支持信用授权，该字段必传
            model.setExtraParam("{\n" +
                    "    \"category\":\"RENT_LIFE_ELECTRIC\",\n" +
                    "    \"serviceId\":\"" + AlipayConfig.getServiceId() + "\",\n" +
                    "    \"outStoreCode\":\"" + outOrderNo + "\",\n" +
                    "    \"outStoreAlias\":\"润来智能\",\n" +
                    "    \"creditExtInfo\":{\n" +
                    "        \"depositAmount\":" + depositAmount + "\n" +
                    "    }\n" +
                    "}");  //outStoreAlias将在用户端信用守护、支付信息、账单详情页展示
            request.setBizModel(model);
            log.info("model: " + JSONObject.toJSONString(model));
            request.setNotifyUrl(AlipayConfig.getNotifyUrl()); //异步通知地址，必填，该接口只通过该参数进行异步通知
            AlipayFundAuthOrderAppFreezeResponse response = alipayClient.sdkExecute(request); //注意这里是sdkExecute，可以获取签名参数
            if (response.isSuccess()) {
                log.info("调用成功");
                log.info("response: {}" + response.getBody()); //签名后的参数，直接入参到
                return response.getBody();
            } else {
                log.error("调用失败:{}, {}", response.getMsg(), response.getSubMsg());
            }
            return response.getBody();
        } catch (Exception e) {
            log.error("fundAuthOrderAppFreeze error:{}", e);
        }
        return "";
    }

    /**
     * 冻结订单查询
     *
     * @throws AlipayApiException
     */
    public String fundAuthOrderQuery(String outOrderNo, String outRequestNo) throws AlipayApiException {
        log.info("outOrderNo: " + outOrderNo);
        log.info("outRequestNo: " + outRequestNo);
        AlipayFundAuthOperationDetailQueryRequest request = new AlipayFundAuthOperationDetailQueryRequest();
        AlipayFundAuthOperationDetailQueryModel model = new AlipayFundAuthOperationDetailQueryModel();
        model.setOutOrderNo(outOrderNo); //替换为实际订单号
        model.setOutRequestNo(outRequestNo); //替换为实际请求单号，保证每次请求都是唯一的
        log.info("model: " + JSONObject.toJSONString(model));
        request.setBizModel(model);
        AlipayFundAuthOperationDetailQueryResponse response = alipayClient.execute(request); //注意这里是sdkExecute，可以获取签名参数
        if (response.isSuccess()) {
            log.info("调用成功");
            log.info("response: {}" + response.getBody()); //签名后的参数，直接入参到
            return response.getBody();
        } else {
            log.error("调用失败");
            return "调用失败";
        }
    }

    /**
     * 芝麻信用单
     *
     * @throws AlipayApiException
     */
    public String credit(String outOrderNo) throws AlipayApiException {
        log.info("outOrderNo: " + outOrderNo);
        ZhimaMerchantOrderRentCreateRequest request = new ZhimaMerchantOrderRentCreateRequest();
        ZhimaMerchantOrderRentCreateModel model = new ZhimaMerchantOrderRentCreateModel();
        model.setOutOrderNo(outOrderNo); //替换为实际订单号
        model.setInvokeType("WINDOWS");
        model.setInvokeReturnUrl(AlipayConfig.getNotifyUrl());
        model.setProductCode("w1010100000000002858");
        model.setGoodsName("衔电充电宝");
        model.setRentUnit("YUAN_ONCE: 元/次");
        model.setRentAmount("0.01");
        model.setDepositAmount("99");
        model.setDepositState("N");
        log.info("model: " + JSONObject.toJSONString(model));
        request.setBizModel(model);
        ZhimaMerchantOrderRentCreateResponse response = alipayClient.execute(request); //注意这里是sdkExecute，可以获取签名参数
        if (response.isSuccess()) {
            log.info("调用成功");
            log.info("response: {}" + response.getBody()); //签名后的参数，直接入参到
            return response.getBody();
        } else {
            log.error("调用失败");
            return "调用失败";
        }
    }

    /**
     * 冻结转支付
     *
     * @param outOrderNo
     * @param authNo
     * @throws AlipayApiException
     */
    public String authToPay(String authNo, String outOrderNo) throws AlipayApiException {
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        AlipayTradePayModel model = new AlipayTradePayModel();
        model.setAuthNo(authNo);  // 填写预授权冻结交易号
        model.setOutTradeNo(outOrderNo);  // 预授权转支付商户订单号，为新的商户交易流水号；如果重试发起扣款，商户订单号不要变；
        model.setProductCode("PRE_AUTH_ONLINE");  // 固定值PRE_AUTH_ONLINE
        model.setSubject("预授权转支付测试");  // 解冻转支付标题，用于展示在支付宝账单中
        model.setTotalAmount("0.01");  // 结算支付金额
        model.setSellerId(AlipayConfig.getPayeeUserId());  // 填写卖家支付宝账户pid
        model.setBuyerId("2088902540342629");  // 填写预授权用户uid，通过预授权冻结接口返回的payer_user_id字段获取
        model.setStoreId(outOrderNo);  // 填写实际交易发生的终端编号，与预授权的outStoreCode保持一致即可
        model.setBody("预授权解冻转支付测试");  // 可填写备注信息
        model.setAuthConfirmMode("COMPLETE"); //必须使用COMPLETE,传入该值用户剩余金额会自动解冻
        request.setBizModel(model);
        request.setNotifyUrl(AlipayConfig.getNotifyUrl()); //异步通知地址，必填，该接口只通过该参数进行异步通知

        AlipayTradePayResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            System.out.println("调用成功");
            log.info("response: {}" + response.getBody());
            return response.getBody();
        } else {
            System.out.println("调用失败");
        }
        return "调用失败:" + response.getMsg();
    }

    /**
     * 冻结转支付
     *
     * @param payModel
     * @throws AlipayApiException
     */
    public String authToPay(AlipayAuth2PayModel payModel) {
        try {
            log.info("authToPay payModel:{}",JSONObject.toJSONString(payModel));
            AlipayTradePayRequest request = new AlipayTradePayRequest();
            AlipayTradePayModel model = new AlipayTradePayModel();
            model.setAuthNo(payModel.getAuthNo());  // 填写预授权冻结交易号
            model.setOutTradeNo(payModel.getOutOrderNo());  // 预授权转支付商户订单号，为新的商户交易流水号；如果重试发起扣款，商户订单号不要变；
            model.setProductCode("PRE_AUTH_ONLINE");  // 固定值PRE_AUTH_ONLINE
            model.setSubject(payModel.getSubject());  // 解冻转支付标题，用于展示在支付宝账单中
            model.setTotalAmount(payModel.getAmount());  // 结算支付金额
            model.setSellerId(AlipayConfig.getPayeeUserId());  // 填写卖家支付宝账户pid
            model.setBuyerId(payModel.getUserId());  // 填写预授权用户uid，通过预授权冻结接口返回的payer_user_id字段获取
            model.setStoreId(payModel.getOutOrderNo());  // 填写实际交易发生的终端编号，与预授权的outStoreCode保持一致即可
            model.setBody(payModel.getBody());  // 可填写备注信息
            model.setAuthConfirmMode("COMPLETE"); //必须使用COMPLETE,传入该值用户剩余金额会自动解冻
            request.setBizModel(model);
            request.setNotifyUrl(AlipayConfig.getNotifyUrl()); //异步通知地址，必填，该接口只通过该参数进行异步通知
            AlipayTradePayResponse response = alipayClient.execute(request);
            log.info("authToPay response:{}",JSONObject.toJSONString(response));
            if (response.isSuccess()) {
                log.info("response: {}" + response.getBody());
                return response.getBody();
            } else {
                log.error("冻结转支付结果：调用失败");
            }
            return "冻结转支付调用失败";
        } catch (Exception e) {
            log.error("authToPay error:{}", e);
            return "冻结转支付调用失败:{}" + e.getMessage();
        }
    }

    /**
     * 退单
     *
     * @throws AlipayApiException
     */
    public String fundAuthOrderCancel(String outOrderNo, String outRequestNo) throws AlipayApiException {
        AlipayFundAuthOperationCancelRequest request = new AlipayFundAuthOperationCancelRequest();
        AlipayFundAuthOperationCancelModel model = new AlipayFundAuthOperationCancelModel();
        model.setOutOrderNo(outOrderNo);
        model.setOutRequestNo(outRequestNo);
        model.setRemark("请求退单");
        request.setBizModel(model);
        request.setNotifyUrl(AlipayConfig.getNotifyUrl());
        log.info("model: " + JSONObject.toJSONString(model));
        AlipayFundAuthOperationCancelResponse response = alipayClient.execute(request);
        log.info("response: {}" + response.getBody());
        return response.getBody();
    }

    /**
     * 金额解冻
     *
     * @throws AlipayApiException
     */
    public String fundAuthOrderUnFreeze(String authNo, String outRequestNo,String amount) throws AlipayApiException {
        AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest();
        AlipayFundAuthOrderUnfreezeModel model = new AlipayFundAuthOrderUnfreezeModel();
        model.setAuthNo(authNo);  // 支付宝资金授权订单号，在授权冻结成功时返回需要入库保存
        model.setOutRequestNo(outRequestNo); //同一商户每次不同的资金操作请求，商户请求流水号不能重复,且与冻结流水号不同
        model.setAmount(amount);  // 本次操作解冻的金额，单位为：元（人民币），精确到小数点后两位
        model.setRemark("预授权解冻");  // 商户对本次解冻操作的附言描述，长度不超过100个字母或50个汉字
        //选填字段，信用授权订单，针对信用全免订单，传入该值完结信用订单，形成芝麻履约记录
        model.setExtraParam("{\"unfreezeBizInfo\":\"{\\\"bizComplete\\\":\\\"true\\\"}\"}");
        request.setBizModel(model);
        request.setNotifyUrl(AlipayConfig.getNotifyUrl());
        log.info("model: " + JSONObject.toJSONString(model));
        AlipayFundAuthOrderUnfreezeResponse response = alipayClient.execute(request);
        log.info("response: {}" + response.getBody());
        return response.getBody();
    }


    // 服务端获取access_token、user_id
    public AlipaySystemOauthTokenResponse getAccessToken(String authCode) throws Exception {
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(authCode);    // 4. 填入前端传入的授权码authCode
        request.setRefreshToken("201208134b203fe6c11548bcabd8da5bb087a83b");  // 0. 不用管
        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);

        return response;
    }

    // 获取支付宝用户信息
    public AlipayUserInfoShareResponse getAliUserInfo(String accessToken) throws Exception {
        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        AlipayUserInfoShareResponse response = alipayClient.execute(request, accessToken);
        if (response.isSuccess()) {
            log.info("获取会员信息 - 调用成功");
            return response;
        }

        return null;
    }

}
